using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Runtime.Serialization;
using System.Security.Permissions;
using System.Web;
using Microsoft.ApplicationBlocks.ExceptionManagement;

namespace Dimok.Exceptions{

	////////////////////////////////////////////////////////////////////////////////////////////////////
	/// <summary>	Name value collection ex. </summary>
	///
	/// <remarks>	Dimon, 12/21/2010. </remarks>
	////////////////////////////////////////////////////////////////////////////////////////////////////

	class NameValueCollectionEx : NameValueCollection {

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Default constructor. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public NameValueCollectionEx() : base() { }

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Constructor. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="nameValue">	A variable-length parameters list containing name value. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public NameValueCollectionEx(params string[] nameValue)
			: base() {
			for (int i = 0; i < nameValue.Length; i += 2)
				this.Add(nameValue[i], nameValue[i + 1]);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	string casting operator. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="nvc">	The nvc. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static implicit operator string(NameValueCollectionEx nvc) {
			if (nvc == null) return "";
			List<string> al = new List<string>();
			foreach (string key in nvc.Keys)
				al.Add(key + ":" + nvc[key]);
			return string.Join("\n\t", al.ToArray());
		}
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	/// <summary>	Exception for signalling asp errors. </summary>
	///
	/// <remarks>	Dimon, 12/21/2010. </remarks>
	////////////////////////////////////////////////////////////////////////////////////////////////////

	public class ASPException : BaseApplicationException {
		private const string DEFAULT_MESSGAE = "";
		private string m_userName = "";

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Default constructor. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public ASPException() : this(DEFAULT_MESSGAE) {}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Constructor. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="message">	The message. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public ASPException(string message) : this(message,null) {}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Constructor. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="inner">	The inner. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public ASPException(Exception inner) : this(DEFAULT_MESSGAE,inner) {}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Constructor. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="message">	The message. </param>
		/// <param name="inner">		The inner. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public ASPException(string message, Exception inner) : this(message, inner, null) { }

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Constructor. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="exc">				The exc. </param>
		/// <param name="namedVaues">	A variable-length parameters list containing named vaues. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public ASPException(Exception exc, params string[] namedVaues) : this("", exc, new NameValueCollectionEx(namedVaues)) { }

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Constructor. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="inner">									The inner. </param>
		/// <param name="additionalInformation">	Information describing the additional. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public ASPException(Exception inner, NameValueCollection additionalInformation) : this(DEFAULT_MESSGAE, inner, additionalInformation) { }

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Constructor. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="message">								The message. </param>
		/// <param name="inner">									The inner. </param>
		/// <param name="additionalInformation">	Information describing the additional. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public ASPException(string message, Exception inner, NameValueCollection additionalInformation) : base(CleanMessage(message), inner) {
			try { AdditionalInformation.Add("ASPException.WebName", HttpContext.Current.Request["SERVER_NAME"]); } catch { }
			try { AdditionalInformation.Add("ASPException.IPAddress", HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"]); } catch { }
			if (additionalInformation != null) AdditionalInformation.Add(additionalInformation);
			Publish();
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Constructor. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="info">			The information. </param>
		/// <param name="context">	The context. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		protected ASPException(SerializationInfo info, StreamingContext context) : base (info, context) {  
			m_userName = info.GetString("m_userName");
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Override the GetObjectData method to serialize custom values. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="info">			Represents the SerializationInfo of the exception. </param>
		/// <param name="context">	Represents the context information of the exception. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		[SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
		public override void GetObjectData(SerializationInfo info, StreamingContext context) {
			// Serialize this class' state and then call the base class GetObjectData
			info.AddValue("m_userName", m_userName, typeof(string));
			base.GetObjectData(info, context);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets the name of the user. </summary>
		///
		/// <value>	The name of the user. </value>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public string userName{get{try{return HttpContext.Current.User.Identity.Name;}catch{return "";}}}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Clean message. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="message">	The message. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		protected static string CleanMessage(string message) {
			message = message.Replace("\nThe transaction ended in the trigger. The batch has been aborted.", "");
			message = message.Replace("\nThe ROLLBACK TRANSACTION request has no corresponding BEGIN TRANSACTION.", "");
			return message.Replace("\nThe statement has been terminated.", "");

		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets the messages. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="exc">	The exc. </param>
		///
		/// <returns>	The messages. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static string GetMessages(Exception exc) {
			if (exc == null) return "";
			List<string> alMsg = new List<string>();
			do {
				if (exc.GetType() != typeof(HiddenException))
					alMsg.Add(exc.Message);
			} while ((exc = exc.InnerException) != null);
			return CleanMessage(string.Join(Environment.NewLine, alMsg.ToArray()));
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Publishes this object. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public void Publish() { ExceptionManager.Publish(this, this.AdditionalInformation); }

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Publishes this object. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="exc">	The exc. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static void Publish(Exception exc){Publish(exc,(NameValueCollection)null);}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Publishes this object. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="exc">			The exc. </param>
		/// <param name="call911">	true to call 911. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static void Publish(Exception exc,bool call911){Publish(exc,null,call911);}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Publishes this object. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="exc">					The exc. </param>
		/// <param name="namedValues">	A variable-length parameters list containing named values. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static void Publish(Exception exc, params string[] namedValues) {
			Publish(exc, (NameValueCollection)new NameValueCollectionEx(namedValues));
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Publishes this object. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="exc">						The exc. </param>
		/// <param name="additionalInfo">	Information describing the additional. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static void Publish(Exception exc,NameValueCollection additionalInfo){
			Publish(exc,additionalInfo,false);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Publishes this object. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="exc">						The exc. </param>
		/// <param name="additionalInfo">	Information describing the additional. </param>
		/// <param name="call911">				true to call 911. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static void Publish(Exception exc,NameValueCollection additionalInfo,bool call911){
			if (null == additionalInfo) additionalInfo = new NameValueCollection();
			try{additionalInfo.Add("ASPException.WebName", HttpContext.Current.Request["SERVER_NAME"]);}catch{}
			try{additionalInfo.Add("ASPException.IPAddress", HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"]);}catch{}
			if( call911 )additionalInfo["Call911"] = true+"";
			ExceptionManager.Publish(exc,additionalInfo);
		}
	}


}